"""
用户数据模型类

"""
from datetime import datetime
from time import time

from flask_login import UserMixin
from peewee import CharField, ForeignKeyField, BooleanField, IntegerField, TextField, DateTimeField
from playhouse.shortcuts import model_to_dict
from werkzeug.security import generate_password_hash, check_password_hash

from models.base_model import MetaBaseModel, BaseModel


class Role(BaseModel):
    """
    管理员角色分类
    """
    name = CharField()
    update_time = DateTimeField(default=datetime.now, null=True)
    enable = BooleanField(default=True, verbose_name='是否启用')

    class Meta:
        table_name = 'xingxiu_role'


class Permission(BaseModel):
    """
    权限
    """
    TYPE_MAP = ((1, '主菜单'), (2, '子菜单'), (3, '按钮'))
    type = IntegerField(choices=TYPE_MAP, verbose_name='成员类型', default=2)
    name = CharField()
    code = CharField(null=True)
    path = CharField()
    enable = BooleanField(default=True)
    parent = ForeignKeyField('self', null=True)
    visible = BooleanField(default=True)  # 是否显示在菜单上
    icon = CharField(null=True)
    component = CharField(null=True)
    component_name = CharField(null=True)
    update_time = DateTimeField(default=datetime.now, null=True)

    class Meta:
        table_name = 'xingxiu_permission'


class UserRolePermission(BaseModel):
    role = ForeignKeyField(Role, backref='role_permissions')
    permission = ForeignKeyField(Permission, backref='role_permissions')
    update_time = DateTimeField(default=datetime.now, null=True)

    class Meta:
        table_name = 'xingxiu_role_permission'


class Organization(BaseModel):
    name = CharField()
    address = CharField(max_length=200, null=True)
    company_type = CharField(max_length=128, null=True)
    phone = CharField(max_length=16, null=True)
    is_final = BooleanField(default=True)
    parent = ForeignKeyField('self', null=True)
    logo = CharField(null=True)  # Assuming logo is a file path
    tenant_id = CharField(max_length=64, null=True)
    wx_refer = BooleanField(default=False)
    wx_css = CharField(max_length=255, null=True)
    pc_css = CharField(max_length=255, null=True)
    is_show_price = BooleanField(default=False)
    no = CharField(max_length=255, null=True)
    inviter = CharField(max_length=255, null=True)
    is_pass_through = BooleanField(default=False)
    official_name = CharField(max_length=255, null=True)
    TYPE_MAP = (('tenant', '租户'), ('body', '主体'), ('sale', '销售'))
    type = CharField(max_length=255, choices=TYPE_MAP, default='tenant')
    build_by_self = BooleanField(default=False)
    is_pass_for_fault = BooleanField(default=False)
    platform_name = CharField(max_length=255, null=True, default='星宿平台')
    platform_logo = CharField(null=True)

    class Meta:
        table_name = 'xingxiu_organization'

    def get_standard_obj(self):
        org = model_to_dict(self, exclude=[Organization.is_del, Organization.parent])
        return org


class User(BaseModel, UserMixin):
    name = CharField()
    password_hash = CharField()
    phone = CharField(max_length=16, verbose_name='电话')
    email = CharField(max_length=64, verbose_name='邮箱', null=True)
    is_active = BooleanField(default=True)
    SEX_MAP = ((1, '男'), (2, '女'),)
    sex = IntegerField(choices=SEX_MAP, default=1, verbose_name='性别')

    TYPE_MAP = ((1, '主账号'), (2, '子账号'),)
    type = IntegerField(choices=TYPE_MAP, verbose_name='成员类型', default=2)
    position = CharField(max_length=64, null=True, verbose_name='岗位')
    avatar = CharField(max_length=255, null=True, verbose_name='头像', column_name='avatar_path')
    is_receive_email = BooleanField(default=False, verbose_name='是否接收邮件消息')
    wx_uid = CharField(null=True)
    enable = BooleanField(default=True, verbose_name='是否启用')

    class Meta:
        table_name = 'xingxiu_user'

    def get_standard_obj(self):
        info = model_to_dict(self, exclude=[User.password_hash])
        roles = UserRole.select().where(UserRole.user_id == info['id'])
        info['roles'] = []
        for role in roles:
            info['roles'].append(model_to_dict(role.role, only=[Role.id, Role.name]))
        orgs = UserOrg.select().where(UserOrg.user_id == info['id'])
        info['orgs'] = []
        for org in orgs:
            info['orgs'].append(model_to_dict(org.org, exclude=[Organization.is_del, Organization.parent]))
        return info

    def is_authenticated(self):
        return True

    @property
    def password(self):
        raise AttributeError('该属性不可读')

    @password.setter
    def password(self, pwd):
        self.password_hash = generate_password_hash(pwd)

    def validate_password(self, pwd):
        return check_password_hash(self.password_hash, pwd)


class UserOrg(BaseModel):
    user = ForeignKeyField(User, backref='user_userorg')
    org = ForeignKeyField(Organization, backref='org_userorg')
    update_time = DateTimeField(default=datetime.now, null=True)

    class Meta:
        table_name = 'xingxiu_user_org'


class UserRole(BaseModel):
    role = ForeignKeyField(Role, backref='role_user')
    user = ForeignKeyField(User, backref='user_role')
    update_time = DateTimeField(default=datetime.now, null=True)

    class Meta:
        table_name = 'xingxiu_user_role'


class UserLog(BaseModel):
    TYPE_MAP = (
        ('login', '登录'),
        ('order', '询价')
    )
    SOURCE_MAP = (
        ('for_sms', '短信登录'),
        ('for_pwd', '密码登录'),
        ('for_code', '二维码登录'),
        ('for_wx_phone', '微信小程序手机号登录'),  # 登录
        # 询价
        # 标准
        ('for_region', '地域'),
        ('for_city', '城市'),
        ('for_node_type', '节点类型'),
        ('for_node', '节点信息'),
        ('for_all', 'port整个信息'),
        # 非标
        ('for_location', '位置信息'),
        ('for_address', '详细信息'),
    )

    type = CharField(max_length=200, verbose_name='日志类型', choices=TYPE_MAP, default='login')
    user = ForeignKeyField(User, verbose_name='成员',
                           related_name='log_mem', null=True)
    content = TextField(null=True, verbose_name='日志内容')
    source = CharField(max_length=200, verbose_name='来源', choices=SOURCE_MAP, default='')
    params = TextField(null=True, verbose_name='埋点主参数')

    class Meta:
        table_name = 'xingxiu_user_log'
